package cn.springmix.core.handler;

import cn.springmix.base.lang.entity.R;
import cn.springmix.core.annotation.NotAutoResult;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.core.MethodParameter;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.method.support.ModelAndViewContainer;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.concurrent.Callable;

/**
 * @author xufeng
 * @description: 包装返回值handler
 * @date 2022-04-20 11:33
 */
public class AutoResultReturnHandler implements HandlerMethodReturnValueHandler {

    private static final ObjectMapper objectMapper = new ObjectMapper();


    public ObjectMapper getObjectMapper() {
        return objectMapper;
    }

    /**
     * 加了 NotAutoResult 注解的不做包装处理
     *
     * @param returnType
     * @return
     */
    @Override
    public boolean supportsReturnType(MethodParameter returnType) {
        if(returnType.hasMethodAnnotation( NotAutoResult.class)){
            return false;
        }
        //返回值是Callable类型
        if(Callable.class.isAssignableFrom(returnType.getParameterType())){
            return false;
        }
        //返回值是Callable类型
        if(Callable.class.isAssignableFrom(returnType.getParameterType())){
            return false;
        }
        //返回值是R类型
        if(R.class.isAssignableFrom(returnType.getParameterType())){
            return false;
        }
        //加了ResponseBody才处理
        return AnnotatedElementUtils.hasAnnotation(returnType.getContainingClass(), ResponseBody.class) ||
                returnType.hasMethodAnnotation(ResponseBody.class);
    }

    /**
     * Controller层接口返回值统一封装方法
     *
     * @param returnValue
     * @param returnType
     * @param mavContainer
     * @param webRequest
     */
    @Override
    public void handleReturnValue(Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer,
            NativeWebRequest webRequest) {
        mavContainer.setRequestHandled(true);
        HttpServletResponse response = webRequest.getNativeResponse(HttpServletResponse.class);
        response.setContentType("application/json;charset=UTF-8");
        PrintWriter writer = null;
        try {
            writer = response.getWriter();
            writer.print(getObjectMapper().writeValueAsString(R.OK(returnValue)));
            writer.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (writer != null) {
                writer.close();
            }
        }
    }
}
